package net.pinnoocle.playservice.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.pinnoocle.playcommon.utils.BigDecimalMathUtil;
import net.pinnoocle.playcommon.utils.ConvertUtils;
import net.pinnoocle.playcommon.utils.HelpUtils;
import net.pinnoocle.playdao.dao.OrderDao;
import net.pinnoocle.playdao.dao.ShopDao;
import net.pinnoocle.playdao.dao.UserDao;
import net.pinnoocle.playdao.entity.Group;
import net.pinnoocle.playdao.entity.Master;
import net.pinnoocle.playdao.entity.Script;
import net.pinnoocle.playdao.entity.ShopStatistics;
import net.pinnoocle.playdao.entity.analysis.*;
import net.pinnoocle.playdao.entity.page.PageModel;
import net.pinnoocle.playdao.entity.page.PageQuery;
import net.pinnoocle.playdao.entity.shopPc.homePage.NumberVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author ye
 * @Description
 * @create 2021-11-29 9:25
 */
@Service("analysisService")
public class AnalysisService {

    @Autowired
    UserServiceImpl userService;
    @Autowired
    OrderDao orderDao;
    @Autowired
    UserDao userDao;
    @Autowired
    ShopDao shopDao;
    @Autowired
    ShopStatisticsServiceImpl shopStatisticsService;
    @Autowired
    ScriptServiceImpl scriptService;
    @Autowired
    GroupServiceImpl groupService;
    @Autowired
    MasterServiceImpl masterService;

    /**
     * 获取营业额
     * @param shopId
     * @return
     */
    public TurnoverVo getTurnover(String shopId){
        TurnoverVo turnoverVo = new TurnoverVo();
        //线上
        HashMap<String, Object> onlineTotal = orderDao.orderStatisticsOnOffLine(shopId, 0,null, null);
        double payPriceTotalOnline = Double.parseDouble(onlineTotal.get("payPrice").toString());
        double appointPriceTotalOnline = Double.parseDouble(onlineTotal.get("appointPrice").toString());
        double totalAmountTotalOnline = BigDecimalMathUtil.add(payPriceTotalOnline,appointPriceTotalOnline);
        turnoverVo.setTotalTurnoverOnline(totalAmountTotalOnline);
        //线下
        HashMap<String, Object> offlineTotal = orderDao.orderStatisticsOnOffLine(shopId, 1,null, null);
        double payPriceTotalOffline = Double.parseDouble(offlineTotal.get("payPrice").toString());
        double appointPriceTotalOffline = Double.parseDouble(offlineTotal.get("appointPrice").toString());
        double totalAmountTotalOffline = BigDecimalMathUtil.add(payPriceTotalOffline,appointPriceTotalOffline);
        turnoverVo.setTotalTurnoverOffline(totalAmountTotalOffline);
        //总金额
        double totalAmount = BigDecimalMathUtil.add(totalAmountTotalOnline, totalAmountTotalOffline);
        turnoverVo.setTotalTurnover(totalAmount);
        //本月
        HashMap<String, String> monthStartAndEndTime = HelpUtils.getMonthStartAndEndTime(null);
        String startDate = monthStartAndEndTime.getOrDefault("startDate","");
        String endDate = monthStartAndEndTime.getOrDefault("endDate","");
        HashMap<String, Object> monthAmount = orderDao.orderStatisticsOnOffLine(shopId, null, startDate, endDate);
        double payPriceTotalMonth = Double.parseDouble(monthAmount.get("payPrice").toString());
        double appointPriceTotalMonth = Double.parseDouble(monthAmount.get("appointPrice").toString());
        double totalAmountTotalOMonth = BigDecimalMathUtil.add(payPriceTotalMonth,appointPriceTotalMonth);
        turnoverVo.setMonthTurnover(totalAmountTotalOMonth);
        return turnoverVo;
    }

    /**
     * 实时概况--获取访客数、用户数
     * @param searchDate
     * @param shopId
     * @return
     */
    public DataVo getDataVo(String searchDate,String shopId){
        DataVo dataVo = new DataVo();
        //默认今天
        String today = Objects.isNull(searchDate) ? DateUtil.today() : searchDate;
        //今天
        ShopStatistics shopStatisticsToday = shopStatisticsService.getOne(new QueryWrapper<ShopStatistics>()
                .lambda()
                .eq(StringUtils.isNotBlank(shopId),ShopStatistics::getShopId, shopId)
                .eq(ShopStatistics::getDateTime, today),false);
        if(Objects.nonNull(shopStatisticsToday)){
            dataVo.setVisitorNumToday(shopStatisticsToday.getVisitorNum());
            dataVo.setBrowserNumToday(shopStatisticsToday.getPageView());
            dataVo.setPayUserNumToday(shopStatisticsToday.getPayUserNum());
            dataVo.setOrderNumToday(shopStatisticsToday.getPayOrderNum());
        }
        DateTime yesterdayDate = DateUtil.offsetDay(DateUtil.parse(today), -1);
        String yesterdayStr = DateUtil.format(yesterdayDate, "yyyy-MM-dd");
        //昨天
        ShopStatistics shopStatisticsYesterday = shopStatisticsService.getOne(new QueryWrapper<ShopStatistics>()
                .lambda()
                .eq(StringUtils.isNotBlank(shopId),ShopStatistics::getShopId, shopId)
                .eq(ShopStatistics::getDateTime, yesterdayStr),false);
        if(Objects.nonNull(shopStatisticsYesterday)){
            dataVo.setVisitorNumYesterday(shopStatisticsYesterday.getVisitorNum());
            dataVo.setBrowserNumYesterday(shopStatisticsYesterday.getPageView());
            dataVo.setPayUserNumYesterday(shopStatisticsYesterday.getPayUserNum());
            dataVo.setOrderNumYesterday(shopStatisticsYesterday.getPayOrderNum());
        }
        return dataVo;
    }

    /**
     * 门店收入走势图
     * @param shopId
     * @return
     */
    public ShopOrderVo shopOrderTrend(String shopId){
        ShopOrderVo shopOrderVo = new ShopOrderVo();
        //今日开始结束时间
        HashMap<String, String> dayStartAndEndTime = HelpUtils.getDayStartAndEndTime(null);
        String todayStartDate = dayStartAndEndTime.get("startDate");
        String todayEndDate = dayStartAndEndTime.get("endDate");
        //今日总收入
        BigDecimal totalPriceToday = orderDao.shopOrderStatisticsByHour(shopId, todayStartDate, todayEndDate, null);
        double totalPriceTodayDouble = totalPriceToday.doubleValue();
        shopOrderVo.setTotalPriceToday(totalPriceTodayDouble);

        //今日已支付总收入
        BigDecimal totalPriceTodayHasPay = orderDao.shopOrderStatisticsByHour(shopId, todayStartDate, todayEndDate, 1);
        double totalPriceTodayHasPayDouble = totalPriceTodayHasPay.doubleValue();
        shopOrderVo.setPayPriceToday(totalPriceTodayHasPayDouble);

        //昨天开始结束时间
        DateTime yesterday = DateUtil.yesterday();
        String yesterdayStartDate = DateUtil.format(DateUtil.beginOfDay(yesterday),"yyyy-MM-dd HH:mm:ss");
        String yesterdayEndDate = DateUtil.format(DateUtil.endOfDay(yesterday),"yyyy-MM-dd HH:mm:ss");
        //昨日总收入
        BigDecimal totalPriceYesterday = orderDao.shopOrderStatisticsByHour(shopId, yesterdayStartDate, yesterdayEndDate, null);
        double totalPriceYesterdayDouble = totalPriceYesterday.doubleValue();
        shopOrderVo.setTotalPriceYesterday(totalPriceYesterdayDouble);

        //订单走势图
        OrderTrendVo orderTrendVo = new OrderTrendVo();
        List<Map<String, Double>> mapListToday = new ArrayList<>();
        List<Map<String, Double>> mapListYesterday = new ArrayList<>();
        //今日走势图
        String today = DateUtil.today();
        String startTime = "";
        String endTime = "";
        for (int i = 0; i < 23; i++) {
            HashMap<String, Double> trendMap = new HashMap<>();
            if(i <= 9){
                startTime = today + " 0" + i +":00:00";
                endTime = today + " 0" + i +":59:59";
            }else{
                startTime = today + " " + i + ":00:00";
                endTime = today + " " + i + ":59:59";
            }
            BigDecimal priceHour = orderDao.shopOrderStatisticsByHour(shopId, startTime, endTime, null);
            trendMap.put(i + "", priceHour.doubleValue());
            mapListToday.add(trendMap);
        }
        //昨日走势图
        String yesterdayStr = DateUtil.format(yesterday, "yyyy-MM-dd");
        String startTimeYesterday = "";
        String endTimeYesterday = "";
        for (int h = 0; h < 23; h++) {
            HashMap<String, Double> trendMapYesterday = new HashMap<>();
            if(h <= 9){
                startTimeYesterday = yesterdayStr + " 0" + h +":00:00";
                endTimeYesterday = yesterdayStr + " 0" + h +":59:59";
            }else{
                startTimeYesterday = yesterdayStr + " " + h + ":00:00";
                endTimeYesterday = yesterdayStr + " " + h + ":59:59";
            }
            BigDecimal priceHour = orderDao.shopOrderStatisticsByHour(shopId, startTimeYesterday, endTimeYesterday, null);
            trendMapYesterday.put(h + "", priceHour.doubleValue());
            mapListYesterday.add(trendMapYesterday);
        }
        Map<String, List<Map<String,Double>>> todayTrendVo = new HashMap<>();
        todayTrendVo.put("today", mapListToday);

        Map<String, List<Map<String,Double>>> yesterdayTrendVo = new HashMap<>();
        todayTrendVo.put("yesterday", mapListYesterday);
        orderTrendVo.setOrderTrendToday(todayTrendVo);
        orderTrendVo.setOrderTrendYesterday(yesterdayTrendVo);
        shopOrderVo.setTrendVo(orderTrendVo);
        return shopOrderVo;
    }

    /**
     * 流量分析
     * @param shopId
     * @return
     */
    public FlowDataVo getFlowData(String shopId){
        FlowDataVo flowDataVo = new FlowDataVo();
        //今天
        String date = DateUtil.today();
        ShopStatistics shopStatisticsToday = shopStatisticsService.getOne(new QueryWrapper<ShopStatistics>()
                .lambda()
                .eq(StringUtils.isNotBlank(shopId),ShopStatistics::getShopId, shopId)
                .eq(ShopStatistics::getDateTime, date),false);
        //昨天
        DateTime yesterday = DateUtil.yesterday();
        String yesterdayStr = DateUtil.format(yesterday, "yyyy-MM-dd");
        ShopStatistics shopStatisticsYesterday = shopStatisticsService.getOne(new QueryWrapper<ShopStatistics>()
                .lambda()
                .eq(StringUtils.isNotBlank(shopId),ShopStatistics::getShopId, shopId)
                .eq(ShopStatistics::getDateTime, yesterdayStr),false);
        //店铺流量
        NumberVo shopNumberVo = new NumberVo();
        int todayVisit = Objects.isNull(shopStatisticsToday) ? 0 : shopStatisticsToday.getVisitorNum();
        int yesterdayVisit = Objects.isNull(shopStatisticsYesterday) ? 0 : shopStatisticsYesterday.getVisitorNum();
        HashMap<String, Object> shopNumberTrend = HelpUtils.getNumberTrendValue(todayVisit, yesterdayVisit);
        shopNumberVo.setTodayNum(todayVisit);
        shopNumberVo.setYesterdayNum(yesterdayVisit);
        shopNumberVo.setTrendType((Integer) shopNumberTrend.get("trendType"));
        shopNumberVo.setTrendValue((String) shopNumberTrend.get("trendValue"));
        flowDataVo.setScriptNumber(shopNumberVo);

        //组局流量
        NumberVo groupNumberVo = new NumberVo();
        int todayGroupVisit = Objects.isNull(shopStatisticsToday) ? 0 : shopStatisticsToday.getGroupVisitorNum();
        int yesterdayGroupVisit = Objects.isNull(shopStatisticsYesterday) ? 0 : shopStatisticsYesterday.getGroupVisitorNum();
        HashMap<String, Object> groupNumberTrend = HelpUtils.getNumberTrendValue(todayGroupVisit, yesterdayGroupVisit);
        groupNumberVo.setTodayNum(todayGroupVisit);
        groupNumberVo.setYesterdayNum(yesterdayGroupVisit);
        groupNumberVo.setTrendType((Integer) groupNumberTrend.get("trendType"));
        groupNumberVo.setTrendValue((String) groupNumberTrend.get("trendValue"));
        flowDataVo.setGroupNumber(groupNumberVo);

        //剧本流量
        NumberVo scriptNumberVo = new NumberVo();
        int todayScriptVisit = Objects.isNull(shopStatisticsToday) ? 0 : shopStatisticsToday.getScriptVisitorNum();
        int yesterdayScriptVisit = Objects.isNull(shopStatisticsYesterday) ? 0 : shopStatisticsYesterday.getScriptVisitorNum();
        HashMap<String, Object> scriptNumberTrend = HelpUtils.getNumberTrendValue(todayScriptVisit, yesterdayScriptVisit);
        scriptNumberVo.setTodayNum(todayScriptVisit);
        scriptNumberVo.setYesterdayNum(yesterdayScriptVisit);
        scriptNumberVo.setTrendType((Integer) scriptNumberTrend.get("trendType"));
        scriptNumberVo.setTrendValue((String) scriptNumberTrend.get("trendValue"));
        flowDataVo.setScriptNumber(scriptNumberVo);

        return flowDataVo;
    }

    /**
     * 流量分析---分页数据
     * @param params
     * @param shopId
     * @return
     */
    public PageModel<FlowDataListPage> flowDataPage(FlowDataListSearchParams params,String shopId){
        Map<String,Object> pageMap = new HashMap<>();
        pageMap.put("page",String.valueOf(params.getPage()));
        pageMap.put("pageSize",String.valueOf(params.getPageSize()));

        if(StringUtils.isNotBlank(shopId)){
            params.setShopId(shopId);
        }
        Page<FlowDataListPage> list = userDao.flowDataPage(
                new PageQuery<ShopStatistics>(pageMap).getPage(),params);
        List<FlowDataListPage> records = list.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return new PageModel<>(list, new ArrayList<>());
        }
        return new PageModel<>(list, records);
    }

    /**
     * 店铺访问量趋势图
     * @param shopId
     * @return
     */
    public List<Map<String,Integer>> shopVisitTendencyChart(String shopId){
        List<Map<String, Integer>> mapList = new ArrayList<>();
        for (int i = 1; i <=7 ; i++) {
            HashMap<String, Integer> stringIntegerHashMap = new HashMap<>();
            String today = DateUtil.today();
            DateTime date = DateUtil.offsetDay(DateUtil.parse(today), -i);
            String dateStr = DateUtil.formatDate(date);
            ShopStatistics shopStatisticsToday = shopStatisticsService.getOne(new QueryWrapper<ShopStatistics>()
                    .lambda()
                    .eq(StringUtils.isNotBlank(shopId),ShopStatistics::getShopId, shopId)
                    .eq(ShopStatistics::getDateTime, dateStr),false);
            int visitNum = Objects.isNull(shopStatisticsToday) ? 0 : shopStatisticsToday.getVisitorNum();
            stringIntegerHashMap.put(dateStr,visitNum);
            mapList.add(stringIntegerHashMap);
        }
        return mapList;
    }

    /**
     * 店铺分析
     * @param shopId
     * @return
     */
    public ShopAnalysisVo shopAnalysis(String shopId){
        //上架剧本库数量
        int scriptLibraryNum = scriptService.count(new QueryWrapper<Script>()
                .lambda()
                .eq(StringUtils.isNotBlank(shopId),Script::getShopId, shopId)
                .eq(Script::getIsDisable, 0)
                .eq(Script::getSourceType, 0));
        //上架本地剧本数量
        int scriptNum = scriptService.count(new QueryWrapper<Script>()
                .lambda()
                .eq(StringUtils.isNotBlank(shopId),Script::getShopId, shopId)
                .eq(Script::getIsDisable, 0)
                .eq(Script::getSourceType, 1));
        //开局数
        int groupNum = groupService.count(new QueryWrapper<Group>()
                .lambda()
                .eq(StringUtils.isNotBlank(shopId),Group::getShopId, shopId)
                .ne(Group::getGroupType, 4));
        //在职DM数
        int masterCount = masterService.count(new QueryWrapper<Master>()
                .lambda()
                .eq(StringUtils.isNotBlank(shopId),Master::getShopId, shopId)
                .eq(Master::getJobStatus, 0)
                .eq(Master::getIsCheck, 1)
                .le(Master::getExpireDate, new Date()));
        //今日在职DM数
        int masterCountToday = masterService.count(new QueryWrapper<Master>()
                .lambda()
                .eq(StringUtils.isNotBlank(shopId),Master::getShopId, shopId)
                .eq(Master::getJobStatus, 0)
                .eq(Master::getIsCheck, 1)
                .eq(Master::getIsRest, 0)
                .le(Master::getExpireDate, new Date()));
        ShopAnalysisVo shopAnalysisVo = new ShopAnalysisVo();
        shopAnalysisVo.setScriptLibraryNum(scriptLibraryNum);
        shopAnalysisVo.setScriptNum(scriptNum);
        shopAnalysisVo.setGroupNum(groupNum);
        shopAnalysisVo.setMasterNum(masterCount);
        shopAnalysisVo.setMasterTodayNum(masterCountToday);
        return shopAnalysisVo;
    }

    /**
     * 根据收入获取剧本排行
     * @param shopId
     * @return
     */
    public List<ScriptTotalAmountList> scriptListByAmount(String shopId){
        List<Script> scriptList = scriptService.list(new QueryWrapper<Script>()
                .lambda()
                .eq(StringUtils.isNotBlank(shopId),Script::getShopId, shopId)
                .gt(Script::getTotalAmount,0)
                .orderByDesc(Script::getTotalAmount)
                .last("LIMIT 10"));
        return ConvertUtils.sourceToTarget(scriptList,ScriptTotalAmountList.class);
    }

    /**
     * 获取多日无收入剧本
     * @param shopId
     * @return
     */
    public List<ScriptTotalAmountList> scriptListNoAmount(String shopId){
        List<Script> scriptList = scriptService.list(new QueryWrapper<Script>()
                .lambda()
                .eq(StringUtils.isNotBlank(shopId),Script::getShopId, shopId)
                .eq(Script::getTotalAmount,0)
                .orderByAsc(Script::getLastIncomeDate)
                .last("LIMIT 10"));
        return ConvertUtils.sourceToTarget(scriptList,ScriptTotalAmountList.class);
    }
}
